package panda.client.ui.widgets;

import java.util.List;

import panda.client.Cardpanda;
import panda.client.JSNI;
import panda.client.engine.MagicCard;
import panda.client.enumerations.ZIndexLevel;
import panda.client.listeners.LabelWithContainerMouseHandler;
import panda.client.services.DataService;
import panda.client.services.DataServiceAsync;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Dialog for loading MagicCardTokens from server.
 * 
 * @author zane.tian@gmail.com
 */
public class TokenSummonDialog extends Composite {
	private boolean open;

	private List<MagicCard> clientTokenDB;
	private VerticalPanel shell;
	private HorizontalPanel hp;
	private SuggestBox box;
	private Button submit;
	private Label dragLabel;

	private final static DataServiceAsync dataServiceAsync = GWT.create(DataService.class);

	public TokenSummonDialog() {
		submit = new Button("Reveal");

		dataServiceAsync.getAllTokensFromStandard(new AsyncCallback<List<MagicCard>>() {
			public void onSuccess(List<MagicCard> result) {
				clientTokenDB = result;

				MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
				for(MagicCard token : clientTokenDB) {
					oracle.add(token.toString());
				}

				box = new SuggestBox(oracle);
				box.setAnimationEnabled(false);

				submit.addClickHandler(new ClickHandler() {
					private boolean found = false;

					public void onClick(ClickEvent event) {
						for(MagicCard token : clientTokenDB) {
							if(token.toString().equals(box.getText())) {
								found = true;
								/* we know that clientTokenDB is actually a Set (no duplicates) */
								/* clientTokenDB is not implemented as a set because JRE Emulation might not support it */

								Cardpanda.grabTokenByExactIDFromServer(token.getName(), token.getMagicSet(), token.getID());
								break;
							}
						}

						if(!found) {
							NoteTip.get().logPersonalNote("No matching token found.", true);
						}
					}
				});

				hp.add(box);
				hp.add(submit);
			}

			public void onFailure(Throwable caught) {
			/* TODO log this */
			}
		});

		DOM.setStyleAttribute(submit.getElement(), "border", "1px solid black");
		DOM.setStyleAttribute(submit.getElement(), "marginLeft", "2px");

		hp = new HorizontalPanel();
		hp.setSpacing(2);

		open = false;

		dragLabel = new Label("Enter a Token Name");
		JSNI.disableSelection(dragLabel.getElement());

		BinExplorer.setShadedStyle(dragLabel.getElement());
		DOM.setStyleAttribute(dragLabel.getElement(), "borderBottom", "1px solid black");

		shell = new VerticalPanel();
		DOM.setStyleAttribute(shell.getElement(), "border", "1px solid black");
		DOM.setStyleAttribute(shell.getElement(), "backgroundColor", "white");
		shell.addStyleName("binExShell");
		shell.add(dragLabel);
		shell.add(hp);
		initWidget(shell);
		hide();

		DOM.setStyleAttribute(this.getElement(), "zIndex", String.valueOf(ZIndexLevel.TOKENMENU.getZIndex()));

		LabelWithContainerMouseHandler handler = new LabelWithContainerMouseHandler(this);
		dragLabel.addMouseOverHandler(handler);
		dragLabel.addMouseMoveHandler(handler);
		dragLabel.addMouseOutHandler(handler);
		dragLabel.addMouseDownHandler(handler);
		dragLabel.addMouseUpHandler(handler);
	}

	public void hide() {
		open = false;
		setVisible(false);
	}

	public void show() {
		open = true;
		setVisible(true);

		DeferredCommand.addCommand(new Command() {
			public void execute() {
				box.setFocus(true);
				selectAll();
			}
		});
	}

	public boolean isOpen() {
		return open;
	}

	/* taken from TextBoxImpl.class */
	private native void setSelectionRange(Element elem, int pos, int length) /*-{
		try {
		  elem.setSelectionRange(pos, pos + length);
		} catch (e) {
		  // Firefox throws exception if TextBox is not visible, even if attached
		}
	}-*/;

	/* doesn't seem to work unless called within TokenSummonDialog. maybe because of canvas updates? */
	public void selectAll() {
		setSelectionRange(box.getElement(), 0, box.getText().length());
	}
}